{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Indexing / querying JSON documents\n",
    "## Adding a JSON document to an index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'OK'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import redis\n",
    "from redis.commands.json.path import Path\n",
    "import redis.commands.search.aggregation as aggregations\n",
    "import redis.commands.search.reducers as reducers\n",
    "from redis.commands.search.field import TextField, NumericField, TagField\n",
    "from redis.commands.search.indexDefinition import IndexDefinition, IndexType\n",
    "from redis.commands.search.query import NumericFilter, Query\n",
    "\n",
    "\n",
    "r = redis.Redis(host='localhost', port=6379)\n",
    "user1 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Paul John\",\n",
    "        \"email\": \"paul.john@example.com\",\n",
    "        \"age\": 42,\n",
    "        \"city\": \"London\"\n",
    "    }\n",
    "}\n",
    "user2 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Eden Zamir\",\n",
    "        \"email\": \"eden.zamir@example.com\",\n",
    "        \"age\": 29,\n",
    "        \"city\": \"Tel Aviv\"\n",
    "    }\n",
    "}\n",
    "user3 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Paul Zamir\",\n",
    "        \"email\": \"paul.zamir@example.com\",\n",
    "        \"age\": 35,\n",
    "        \"city\": \"Tel Aviv\"\n",
    "    }\n",
    "}\n",
    "\n",
    "user4 = {\n",
    "    \"user\":{\n",
    "        \"name\": \"Sarah Zamir\",\n",
    "        \"email\": \"sarah.zamir@example.com\",\n",
    "        \"age\": 30,\n",
    "        \"city\": \"Paris\"\n",
    "    }\n",
    "}\n",
    "r.json().set(\"user:1\", Path.root_path(), user1)\n",
    "r.json().set(\"user:2\", Path.root_path(), user2)\n",
    "r.json().set(\"user:3\", Path.root_path(), user3)\n",
    "r.json().set(\"user:4\", Path.root_path(), user4)\n",
    "\n",
    "schema = (TextField(\"$.user.name\", as_name=\"name\"),TagField(\"$.user.city\", as_name=\"city\"), NumericField(\"$.user.age\", as_name=\"age\"))\n",
    "r.ft().create_index(schema, definition=IndexDefinition(prefix=[\"user:\"], index_type=IndexType.JSON))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Searching"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Simple search"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Result{2 total, docs: [Document {'id': 'user:1', 'payload': None, 'json': '{\"user\":{\"name\":\"Paul John\",\"email\":\"paul.john@example.com\",\"age\":42,\"city\":\"London\"}}'}, Document {'id': 'user:3', 'payload': None, 'json': '{\"user\":{\"name\":\"Paul Zamir\",\"email\":\"paul.zamir@example.com\",\"age\":35,\"city\":\"Tel Aviv\"}}'}]}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.ft().search(\"Paul\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Filtering search results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Result{1 total, docs: [Document {'id': 'user:3', 'payload': None, 'json': '{\"user\":{\"name\":\"Paul Zamir\",\"email\":\"paul.zamir@example.com\",\"age\":35,\"city\":\"Tel Aviv\"}}'}]}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q1 = Query(\"Paul\").add_filter(NumericFilter(\"age\", 30, 40))\n",
    "r.ft().search(q1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Paginating and Ordering search Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Result{4 total, docs: [Document {'id': 'user:1', 'payload': None, 'age': '42', 'json': '{\"user\":{\"name\":\"Paul John\",\"email\":\"paul.john@example.com\",\"age\":42,\"city\":\"London\"}}'}, Document {'id': 'user:3', 'payload': None, 'age': '35', 'json': '{\"user\":{\"name\":\"Paul Zamir\",\"email\":\"paul.zamir@example.com\",\"age\":35,\"city\":\"Tel Aviv\"}}'}]}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Search for all users, returning 2 users at a time and sorting by age in descending order\n",
    "offset = 0\n",
    "num = 2\n",
    "q = Query(\"*\").paging(offset, num).sort_by(\"age\", asc=False) # pass asc=True to sort in ascending order\n",
    "r.ft().search(q)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Counting the total number of Items"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q = Query(\"*\").paging(0, 0)\n",
    "r.ft().search(q).total"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Projecting using JSON Path expressions "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document {'id': 'user:1', 'payload': None, 'city': 'London'},\n",
       " Document {'id': 'user:3', 'payload': None, 'city': 'Tel Aviv'}]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.ft().search(Query(\"Paul\").return_field(\"$.user.city\", as_field=\"city\")).docs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Aggregation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[b'age', b'35'], [b'age', b'42']]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "req = aggregations.AggregateRequest(\"Paul\").sort_by(\"@age\")\n",
    "r.ft().aggregate(req).rows"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Count the total number of Items"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[b'total', b'4']]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# The group_by expects a string or list of strings to group the results before applying the aggregation function to\n",
    "# each group. Passing an empty list here acts as `GROUPBY 0` which applies the aggregation function to the whole results\n",
    "req = aggregations.AggregateRequest(\"*\").group_by([], reducers.count().alias(\"total\"))\n",
    "r.ft().aggregate(req).rows"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "d45c99ba0feda92868abafa8257cbb4709c97f1a0b5dc62bbeebdf89d4fad7fe"
  },
  "kernelspec": {
   "display_name": "redis-py",
   "language": "python",
   "name": "redis-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
